package imp

import (
	sqlc "bgs/db/sqlc"
	activityGrpc "bgs/grpc/gen/service/activity"
	// commonActivityGrpc "bgs/grpc/gen/shared/common_activity"
	"bgs/grpc/gen/shared/message"
	activityService "bgs/service/activity"
	"bgs/service/model"
	"bgs/util"
	"encoding/json"
	"fmt"

	"context"
	"database/sql"
)

/****************************************************************************************/
/*                               spokesman activity entity of helper                    */
/****************************************************************************************/


/****************************************************************************************/
/*                               spokesman activity entity of cmd                       */
/****************************************************************************************/

// CreateActivityOfS S新增活动
func (s *ActivityAPIService) CreateActivityOfS(ctx context.Context, req *activityGrpc.CreateActivityOfSRequest) (res *activityGrpc.CreateActivityOfSResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("activitySpokesmanObsolete->CreateActivityOfS:%v", req)
	res = &activityGrpc.CreateActivityOfSResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	var activity sqlc.Activity
	var activityProductWithProductInfos []sqlc.ListNormalActivityProductWithProductInfosByActivityIDRow
	var activitySkuWithProductOrProductSpecInfos []*model.ActivitySkuWithProductOrProductSpecInfo
	// var activityConsignment sqlc.ActivityConsignment
	// var normalActivityConsignmentBonusSettings []sqlc.ActivityConsignmentBonusSetting

	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		parentActivity, err := q.GetActivity(ctx, req.ParentId)
		if err != nil {
			if sql.ErrNoRows == err {
				return fmt.Errorf("无法找到代言的活动:%d", req.ParentId)
			}
			return err
		}
		NParentID := sqlc.NInt64FromInt64(parentActivity.ID)

		activity, err = q.CreateActivity(ctx, sqlc.CreateActivityParams{
			BrandID:                       parentActivity.BrandID,
			SpokesmanID:                   sqlc.NInt64FromInt64(req.SpokesmanId),
			PubUserID:                     req.PubUserId,
			Name:                          req.Name,
			Type:                          parentActivity.Type,
			Intro:                         json.RawMessage(req.Intro),
			Begined:                       parentActivity.Begined,
			Ended:                         parentActivity.Ended,
			Background:                    sqlc.NSFromString(req.Background),
			SaleMode:                      parentActivity.SaleMode,
			DeliveryModes:                 parentActivity.DeliveryModes,
			IsUseWarehouseShippingFeeRule: parentActivity.IsUseWarehouseShippingFeeRule,
			UnifiedShippingFee:            parentActivity.UnifiedShippingFee,
			MaxiumPurchaseFrequency:       parentActivity.MaxiumPurchaseFrequency,
			MinimumPurchaseAmount:         parentActivity.MinimumPurchaseAmount,
			Tel:                           req.Tel,
			RootID:                        NParentID, // 目前root_id==parent_id
			ParentID:                      NParentID,
			Owner:                         string(sqlc.EmActivityOwnerSpokesman),
		})
		if err != nil {
			return err
		}
		slog.Infof("1 创建活动S ok")

		// 活动S仓库
		slog.Infof("2 活动S仓库直接读取代言的品牌活动,略过 ok")

		activityProductOfSMap := make(map[int64]bool)
		for _, item := range req.ActivityProductIsShows {
			activityProductOfSMap[item.ProductId] = item.IsShow
		}

		// 活动商品、商品规格
		normalParentActivityProducts, err := q.ListNormalActivityProductsByActivityID(ctx, parentActivity.ID)
		if err != nil {
			return err
		}

		normalParentActivitySkus, err := q.ListNormalActivitySkusByActivityID(ctx, parentActivity.ID)
		if err != nil {
			return err
		}

		var activityProduct sqlc.ActivityProduct
		for _, item1 := range normalParentActivityProducts {
			quantity := util.Int32IfThenElse(item1.Quantity == 0, 1, item1.Quantity)
			activityProduct, err = q.UpsertActivityProduct(ctx, sqlc.UpsertActivityProductParams{
				BrandID:          parentActivity.BrandID,
				ActivityID:       activity.ID,
				RootActivityID:   NParentID, // 目前root_id==parent_id
				ParentActivityID: NParentID,
				ProductID:        item1.ProductID,
				IsShow:           activityProductOfSMap[item1.ProductID],
				PriceMin:         item1.PriceMin,
				PriceMax:         item1.PriceMax,
				Quantity:         quantity,
				SortNo:           item1.SortNo,
			})
			if err != nil {
				return err
			}

			var skusOfCurrentActivityProduct []sqlc.ActivitySku
			skusFiltered := util.Filter(util.ToGenericSlice(normalParentActivitySkus), func(v interface{}) bool {
				val := v.(sqlc.ActivitySku)
				return val.ProductID == item1.ProductID
			})

			for _, v := range skusFiltered {
				skusOfCurrentActivityProduct = append(skusOfCurrentActivityProduct, v.(sqlc.ActivitySku))
			}

			for _, item2 := range skusOfCurrentActivityProduct {
				_, err = q.UpsertActivitySku(ctx, sqlc.UpsertActivitySkuParams{
					BrandID:           parentActivity.BrandID,
					ActivityID:        activity.ID,
					RootActivityID:    NParentID, // 目前root_id==parent_id
					ParentActivityID:  NParentID,
					ActivityProductID: activityProduct.ID,
					ProductID:         item2.ProductID,
					ProductSpecID:     item2.ProductSpecID,
					Price:             item2.Price,
					Maximum:           0, // 0到表这是个活动最大可售数量为0,一般是代言的活动
					ProductSpecKey:    fmt.Sprintf("%d-%d", item2.ProductID, item2.ProductSpecID.Int64),
					StorageKey:        item2.StorageKey,
					SortNo:            item2.SortNo,
				})
				if err != nil {
					return err
				}
			}

		}
		slog.Infof("3 设置活动S商品、商品规格 ok")

		// activityConsignment, normalActivityConsignmentBonusSettings, err = s.activityService.FetchConsignmentAndConsignmentBonusSettings(ctx, q, activity.ParentID.Int64)
		// if err != nil {
		// 	return err
		// }
		// slog.Info("4 读取代言的品牌活动B帮卖帮卖与帮卖奖励设置 ok")

		activityProductWithProductInfos, activitySkuWithProductOrProductSpecInfos, err = s.activityService.FetchNormalProductAndSkus(ctx, q, activity.ID)
		if err != nil {
			return err
		}
		slog.Info("5 读取活动s sku及产品规格信息 ok")

		return
	})

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	// res.ActivityOfS = transformActivityOfSEntityToPb(activityProductWithProductInfos, activitySkuWithProductOrProductSpecInfos, activityConsignment, normalActivityConsignmentBonusSettings)(activity)
	res.ActivityOfS = transformActivityOfSEntityToPb(activityProductWithProductInfos, activitySkuWithProductOrProductSpecInfos)(activity)
	return
}

// UpdateActivityOfS S更新活动
func (s *ActivityAPIService) UpdateActivityOfS(ctx context.Context, req *activityGrpc.UpdateActivityOfSRequest) (res *activityGrpc.UpdateActivityOfSResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("activitySpokesmanObsolete->UpdateActivityOfS:%v", req)
	res = &activityGrpc.UpdateActivityOfSResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}
	var activity sqlc.Activity
	var activityProductWithProductInfos []sqlc.ListNormalActivityProductWithProductInfosByActivityIDRow
	var activitySkuWithProductOrProductSpecInfos []*model.ActivitySkuWithProductOrProductSpecInfo
	// var activityConsignment sqlc.ActivityConsignment
	// var normalActivityConsignmentBonusSettings []sqlc.ActivityConsignmentBonusSetting

	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {

		activity, err = q.UpdateActivityOfS(ctx, sqlc.UpdateActivityOfSParams{
			ID:         req.Id,
			Name:       req.Name,
			Intro:      json.RawMessage(req.Intro),
			Background: sqlc.NSFromString(req.Background),
			Tel:        req.Tel,
		})
		if err != nil {
			return err
		}
		slog.Infof("1 更新活动S ok")

		// 活动S仓库
		slog.Infof("2 更新S仓库直接读取代言的品牌活动,略过 ok")

		activityProductIsShowOfSMap := make(map[int64]bool)
		activityProductSortNoOfSMap := make(map[int64]int32)
		for idx, item := range req.ActivityProductIsShows {
			activityProductIsShowOfSMap[item.ProductId] = item.IsShow
			activityProductSortNoOfSMap[item.ProductId] = int32(1 + idx)
		}

		// 活动商品、商品规格
		normalParentActivityProducts, err := q.ListNormalActivityProductsByActivityID(ctx, activity.ID)
		if err != nil {
			return err
		}
		for _, item1 := range normalParentActivityProducts {
			_, err = q.UpdateActivityProductIsShowAndSortNo(ctx, sqlc.UpdateActivityProductIsShowAndSortNoParams{
				ID:     item1.ID,
				IsShow: activityProductIsShowOfSMap[item1.ProductID],
				SortNo: activityProductSortNoOfSMap[item1.ProductID],
			})
			if err != nil {
				return err
			}
		}
		slog.Infof("3 设置活动S商品is_show ok")

		// activityConsignment, normalActivityConsignmentBonusSettings, err = s.activityService.FetchConsignmentAndConsignmentBonusSettings(ctx, q, activity.ParentID.Int64)
		// if err != nil {
		// 	return err
		// }
		// slog.Info("4 读取代言的品牌活动B帮卖帮卖与帮卖奖励设置 ok")

		activityProductWithProductInfos, activitySkuWithProductOrProductSpecInfos, err = s.activityService.FetchNormalProductAndSkus(ctx, q, activity.ID)
		if err != nil {
			return err
		}
		slog.Info("5 读取活动s sku及产品规格信息 ok")

		return
	})

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	s.activityService.ClearCacheOwn(activity.ID)
	// res.ActivityOfS = transformActivityOfSEntityToPb(activityProductWithProductInfos, activitySkuWithProductOrProductSpecInfos, activityConsignment, normalActivityConsignmentBonusSettings)(activity)
	res.ActivityOfS = transformActivityOfSEntityToPb(activityProductWithProductInfos, activitySkuWithProductOrProductSpecInfos)(activity)
	return
}

// PublishActivityOfS 发布代言活动S
func (s *ActivityAPIService) PublishActivityOfS(ctx context.Context, req *activityGrpc.PublishActivityOfSRequest) (res *activityGrpc.PublishActivityOfSResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("activitySpokesmanObsolete->PublishActivityOfS:%v", req)
	res = &activityGrpc.PublishActivityOfSResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	activityID := req.Id
	activity, err := s.dao.Q.GetActivity(ctx, activityID)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	if activity.Owner != string(sqlc.EmActivityOwnerSpokesman) {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     fmt.Sprintf("代言活动owner[%s]不符合", activity.Owner),
		}
		return
	}
	if activity.PubUserID != req.UserId {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     "不是代言人所有的活动不符合",
		}
		return
	}
	if activity.ProcessStatus != string(sqlc.EmActivityProcessStatusDraft) {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     fmt.Sprintf("活动状态[%s]不允许发布", activity.ProcessStatus),
		}
		return
	}

	parentActivity, err := s.dao.Q.GetActivity(ctx, activity.ParentID.Int64)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	if parentActivity.ProcessStatus != string(sqlc.EmActivityProcessStatusProcessing) {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     fmt.Sprintf("代言的品牌活动[%s]状态不允许", parentActivity.ProcessStatus),
		}
		return
	}

	var toProcessStatus string
	userID := req.UserId
	err = s.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		toProcessStatus, err = s.activityService.PublishActivity(ctx, q, activityService.PublishActivityParam{
			ActivityPtr: &activity,
			UserID:      userID,
		})
		if err != nil {
			return err
		}
		slog.Infof("a 发布代言活动 ok")

		err = s.userService.UpdateUserStatSinceActivityEndorsed(ctx, q, userID)
		if err != nil {
			return err
		}
		slog.Infof("b 发布代言活动后更新到(UserStat) ok")

		err = s.spokesmanService.UpdateEndorseActivityCountSinceActivityPublished(ctx, q, &activity)
		if err != nil {
			return err
		}
		slog.Infof("b 发布代言活动后更新到(Spokesman) ok")
		return
	})

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	s.activityService.ClearCacheOwn(activity.ID)
	res.ProcessStatus = toProcessStatus
	return
}

